package i5.modelman.merge.dependency;



import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import jpl.Atom;
import jpl.Term;
import jpl.Variable;

public class Dependency implements Iterable<Constraint>{
	private List<Constraint> constraints = new LinkedList<Constraint>();
	
	public Dependency(){}
	
	public Dependency(Iterable<? extends Constraint> constraints){
		for(Constraint constraint : constraints){
			addConstraint(constraint);
		}
	}
	
	public Iterator<Constraint> getConstraints(){
		return constraints.iterator();
	}
	
	public void addConstraint(Constraint c){
		constraints.add(c);
	}
	
	public int size(){
		return constraints.size();
	}
	
	public void addConstraints(Iterable<? extends Constraint> constraints){
		for(Constraint c : constraints){
			addConstraint(c);
		}
	}
	
	public void addDependency(Dependency other){
		assert other != this;
		Iterator<Constraint> it = other.getConstraints();
		while(it.hasNext()){
			Constraint c = it.next();
			addConstraint(c);
		}
	}
	
	public void clear(){
		constraints.clear();
	}

	public Iterator<Constraint> iterator() {
		return getConstraints();
	}
	
	public String toString(){
		return constraints.toString();
	}

	/**
	 * Computation of the aggregated length of all constraints
	 * in the dependency. The metric is the number of appearances
	 * of variables and constants in the mapping rules. Multiple
	 * appearances of the same variables are accumulated. functional
	 * terms are also accumulated according to the number of arguments.
	 * 
	 * @return the aggregated length of the dependency.
	 */
	public int computeLength() {
		final int[] length = new int[]{0};
		CompoundWalker lengthCollector = new CompoundWalker(){
		
			@Override
			protected void visit(Variable var) {
				length[0]++;
			}

			@Override
			protected void visitGround(Term t){
				length[0]++;
			}
			
			@Override
			protected void visit(Atom atom) {
				for(Term t :atom.args()){
					visit(t);
				}
			}
			
		};
		for(Constraint c : this){
			lengthCollector.visit(c.getLhs().goal());
			lengthCollector.visit(c.getRhs().goal());
		}
		return length[0];
	}
}
